﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace QLFUI
{
    public partial class ProgressBarEx : QLFControlBase
    {

        #region - 变量 -

        private int value = 0;
        private int maximum = 100;
        private int minimum = 0;
        private Color startColor = Color.FromArgb(189, 225, 114);
        private Color endColor = Color.FromArgb(189, 225, 114);
        private Color backgroundColor = Color.FromArgb(217, 231, 244);
        private Color borderColor = Color.Gray;
        private int topHighlightAlpha = 128;
        private int bottomHighlightAlpha = 25;
        private Color topHighlightColor = Color.White;
        private Color bottomHighlightColor = Color.Transparent;
        private Color animateGlowColor = Color.FromArgb(100, 255, 255, 255);
        private int radius = 5;
        private int glowPosition = -300;
        private bool animate = false;
        private bool showString = false;
        private Color stringColor = Color.Black;

        #endregion

        #region - 属性 -

        [Browsable(false)]
        public new Color BackColor
        {
            get { return base.BackColor; }
            set { base.BackColor = value; this.Invalidate(); }
        }

        [Category("行为"), Description("进度当前值")]
        public int Value
        {
            get { return this.value; }
            set
            {
                if (value > maximum || value < minimum)
                {
                    return;
                }
                this.value = value;
                this.Invalidate();
            }
        }

        [Category("行为"), Description("进度最大值")]
        public int Maximum
        {
            get { return maximum; }
            set { maximum = value; this.Invalidate(); }
        }

        [Category("行为"), Description("进度最小值")]
        public int Minimum
        {
            get { return minimum; }
            set { minimum = value; this.Invalidate(); }
        }

        [Category("QLFUI"), Description("进度条开始的颜色，向结束颜色渐变")]
        public Color StartColor
        {
            get { return startColor; }
            set
            {
                startColor = value;
                this.Invalidate();
            }
        }

        [Category("QLFUI"), Description("进度条结束时颜色")]
        public Color EndColor
        {
            get { return endColor; }
            set
            {
                endColor = value;
                this.Invalidate();
            }
        }

        [Category("QLFUI"), Description("进度条背景色")]
        public Color BackgroundColor
        {
            get { return backgroundColor; }
            set { backgroundColor = value; this.Invalidate(); }
        }

        [Category("QLFUI"), Description("进度条边框颜色")]
        public Color BorderColor
        {
            get { return borderColor; }
            set { borderColor = value; this.Invalidate(); }
        }

        [Category("QLFUI"), Description("进度条顶部高亮颜色")]
        public Color TopHighlightColor
        {
            get { return topHighlightColor; }
            set { topHighlightColor = value; this.Invalidate(); }
        }

        [Category("QLFUI"), Description("进度条底部高亮颜色")]
        public Color BottomHighlightColor
        {
            get { return bottomHighlightColor; }
            set { bottomHighlightColor = value; this.Invalidate(); }
        }

        [Category("QLFUI"), Description("移动的辉光颜色")]
        public Color AnimateGlowColor
        {
            get { return animateGlowColor; }
            set
            {
                int r = value.R;
                int g = value.G;
                int b = value.B;
                animateGlowColor = Color.FromArgb(150, r, g, b);
                this.Invalidate();
            }
        }

        [Category("QLFUI"), Description("边角弯曲半径(1-10),值越大弯曲越明显")]
        public int Radius
        {
            get { return radius; }
            set
            {
                if (value < 0 || value > 10)
                {
                    return;
                }
                radius = value;
                this.Invalidate();
            }
        }

        [Category("QLFUI"), Description("是否允许动画")]
        public bool Animate
        {
            get { return animate; }
            set
            {
                animate = value;
                if (animate)
                {
                    glowTimer.Start();
                }
                else
                {
                    glowTimer.Stop();
                }
                this.Invalidate();
            }
        }

        [Category("QLFUI"), Description("是否显示进度信息")]
        public bool ShowString
        {
            get { return showString; }
            set { showString = value; this.Invalidate(); }
        }

        [Category("QLFUI"), Description("进度文字的颜色")]
        public Color StringColor
        {
            get { return stringColor; }
            set { stringColor = value; this.Invalidate(); }
        }

        [Category("QLFUI"), Description("进度条顶部高亮颜色透明度")]
        public int TopHighlightAlpha
        {
            get { return topHighlightAlpha; }
            set { topHighlightAlpha = value;
                Invalidate(); }
        }

        [Category("QLFUI"), Description("进度条底部高亮颜色透明度透明度")]
        public int BottomHighlightAlpha
        {
            get { return bottomHighlightAlpha; }
            set { bottomHighlightAlpha = value;
                Invalidate(); }
        }

        #endregion

        #region - 构造函数 -

        public ProgressBarEx()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            InitializeComponent();
            this.BackColor = Color.Transparent;
            glowTimer.Interval = 15;
            if (Value < maximum)
            {
                glowTimer.Start();
            }
        }

        #endregion

        #region - 事件 -

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            Rectangle rect = this.ClientRectangle;

            DrawBorder(g, rect);
            DrawBackground(g, rect);
            DrawBar(g, rect);
            DrawBarShadows(g, rect);
            DrawHighlight(g, rect);    //底部的高亮
            DrawAnimateGrow(g, rect);  //移动的辉光
            DrawString(g, rect);  //显示进度信息
        }

        private void glowTimer_Tick(object sender, EventArgs e)
        {
            if (this.animate)
            {
                glowPosition += 10;
                if (glowPosition > this.Width)
                {
                    glowPosition = -300;
                }
                this.Invalidate();
            }
            else
            {
                glowTimer.Stop();
                glowPosition = -300;
            }
        }

        #endregion

        #region - 辅助方法 -

        private Color GetIntermediateColor()
        {
            Color c = this.StartColor;
            Color c2 = this.EndColor;

            float pc = this.Value * 1.0F / (this.maximum - this.minimum);

            int ca = c.A, cr = c.R, cg = c.G, cb = c.B;
            int c2a = c2.A, c2r = c2.R, c2g = c2.G, c2b = c2.B;

            int a = (int)Math.Abs(ca + (ca - c2a) * pc);
            int r = (int)Math.Abs(cr - ((cr - c2r) * pc));
            int g = (int)Math.Abs(cg - ((cg - c2g) * pc));
            int b = (int)Math.Abs(cb - ((cb - c2b) * pc));

            if (a > 255) { a = 255; }
            if (r > 255) { r = 255; }
            if (g > 255) { g = 255; }
            if (b > 255) { b = 255; }

            return (Color.FromArgb(a, r, g, b));
        }

        private void DrawBorder(Graphics g, Rectangle r)
        {
            using (Pen pen = new Pen(borderColor))
            {
                if (radius == 0)
                {
                    g.DrawRectangle(pen, r.X, r.Y, r.Width - 1, r.Height - 1);
                }
                else
                {
                    GraphicsPath rr = DrawRoundRect(r.X, r.Y, r.Width - 2, r.Height - 1, radius);
                    g.DrawPath(pen, rr);
                }
            }
        }

        private void DrawBackground(Graphics g, Rectangle r)
        {
            using (SolidBrush brush = new SolidBrush(backgroundColor))
            {
                if (radius == 0)
                {
                    g.FillRectangle(brush, r.X + 1, r.Y + 1, r.Width - 2, r.Height - 2);
                }
                else
                {
                    GraphicsPath rr = DrawRoundRect(r.X, r.Y, r.Width - 2, r.Height - 1, radius);
                    g.FillPath(brush, rr);
                }
            }

        }

        private void DrawHighlight(Graphics g, Rectangle rect)
        {
            #region 顶部高亮

            Rectangle tr = new Rectangle(1, 1, rect.Width - 3, 6);
            GraphicsPath tp = DrawRoundRect(tr, 2, 2, 0, 0);

            g.SetClip(tp);
            LinearGradientBrush tg = new LinearGradientBrush(tr,Color.FromArgb(topHighlightAlpha,topHighlightColor),
                                                             Color.Transparent,
                                                             LinearGradientMode.Vertical);
            g.FillPath(tg, tp);
            g.ResetClip();

            #endregion

            #region 底部高亮

            Rectangle br = new Rectangle(1, this.Height - 8, this.Width - 3, 6);
            GraphicsPath bp = DrawRoundRect(br, 0, 0, 2, 2);

            g.SetClip(bp);
            LinearGradientBrush bg = new LinearGradientBrush(br,Color.Transparent,
                                                             Color.FromArgb(bottomHighlightAlpha,bottomHighlightColor),
                                                             LinearGradientMode.Vertical);
            g.FillPath(bg, bp);
            g.ResetClip();

            #endregion
        }

        //进度条
        private void DrawBar(Graphics g, Rectangle rect)
        {
            Rectangle r = new Rectangle(1, 1, rect.Width - 3, rect.Height - 3);
            r.Width = (int)(Value * 1.0F / (maximum - minimum) * rect.Width);
            g.FillRectangle(new SolidBrush(GetIntermediateColor()), r);
        }

        private void DrawBarShadows(Graphics g, Rectangle rect)
        {
            //Rectangle lr = new Rectangle(1, 2, 15, rect.Height - 3);
            //LinearGradientBrush lg = new LinearGradientBrush(lr, Color.White, Color.White,
            //                                                 LinearGradientMode.Horizontal);

            //ColorBlend lc = new ColorBlend(3);
            //lc.Colors = new Color[] { Color.Transparent, Color.FromArgb(40, 0, 0, 0), Color.Transparent };
            //lc.Positions = new float[] { 0.0F, 0.2F, 1.0F };
            //lg.InterpolationColors = lc;

            //lr.X--;
            //g.FillRectangle(lg, lr);

            //Rectangle rr = new Rectangle(this.Width - 3, 2, 15, rect.Height - 3);
            //rr.X = (int)(Value * 1.0F / (maximum - minimum) * rect.Width) - 14;
            //LinearGradientBrush rg = new LinearGradientBrush(rr, Color.Black, Color.Black,
            //                                                 LinearGradientMode.Horizontal);

            //ColorBlend rc = new ColorBlend(3);
            //rc.Colors = new Color[] { Color.Transparent, Color.FromArgb(40, 0, 0, 0), Color.Transparent };
            //rc.Positions = new float[] { 0.0F, 0.8F, 1.0F };
            //rg.InterpolationColors = rc;

            //g.FillRectangle(rg, rr);
        }

        private void DrawAnimateGrow(Graphics g, Rectangle rect)
        {
            Rectangle r = new Rectangle(glowPosition, 0, 60, rect.Height);
            LinearGradientBrush lgb = new LinearGradientBrush(r, Color.White, Color.White,
                                                              LinearGradientMode.Horizontal);

            ColorBlend cb = new ColorBlend(4);
            cb.Colors = new Color[] { Color.Transparent, animateGlowColor, animateGlowColor, Color.Transparent };
            cb.Positions = new float[] { 0.0F, 0.5F, 0.6F, 1.0F };
            lgb.InterpolationColors = cb;

            //设置剪辑区域（已经发生的进度范围中）
            Rectangle clip = new Rectangle(1, 2, this.Width - 3, this.Height - 3);
            clip.Width = (int)(Value * 1.0F / (maximum - minimum) * rect.Width);
            g.SetClip(clip);
            g.FillRectangle(lgb, r);
            g.ResetClip();
        }

        private void DrawString(Graphics g, Rectangle rect)
        {
            if (showString)
            {
                using (SolidBrush brush = new SolidBrush(stringColor))
                {
                    string per = ((value / (double)(maximum - minimum)) * 100).ToString() + "%";
                    g.DrawString(per, new Font("宋体", 9), brush, new PointF(this.Width / 2 - 10, this.Height / 2 - 5));
                }
            }
        }

        #endregion

    }
}
